﻿/***************************************************************************
 *
 * Copyright (c) 2022 str2num.com, Inc. All Rights Reserved
 * $Id$
 *
 **************************************************************************/

/**
 * @file async_udp_socket.h
 * @author str2num
 * @version $Revision$
 * @brief
 *
 **/

#ifndef ICE_BASE_LINUX_ASYNC_UDP_SOCKET_H_
#define ICE_BASE_LINUX_ASYNC_UDP_SOCKET_H_

#include <list>

#include <rtc_base/third_party/sigslot/sigslot.h>
#include <rtc_base/socket_address.h>
#include <rtc_base/thread.h>
#include <rtc_base/async_packet_socket.h>

#include "ice/base/linux/event_loop.h"
#include "ice/base/linux/physical_socket_ex.h"

namespace ice
{

    class UdpPacketData
    {
    public:
        UdpPacketData(const char *data, size_t size, const rtc::SocketAddress &addr) : data_(new char[size]),
                                                                                       size_(size),
                                                                                       addr_(addr)
        {
            memcpy(data_, data, size);
        }

        ~UdpPacketData()
        {
            if (data_)
            {
                delete[] data_;
                data_ = nullptr;
            }
        }

        char *data() { return data_; }
        size_t size() { return size_; }
        const rtc::SocketAddress &addr() { return addr_; }

    private:
        char *data_;
        size_t size_;
        rtc::SocketAddress addr_;
    };

    class AsyncUdpSocket
    {
    public:
        AsyncUdpSocket(EventLoop *el, int sock);
        ~AsyncUdpSocket();

        void RecvData();
        void SendData();

        // int Send(const void *, size_t, const rtc::PacketOptions &) override { return -1; }
        int SendTo(const void *data, size_t size, const rtc::SocketAddress &addr,
                   const rtc::PacketOptions &options);

        int Close();
        sigslot::signal5<AsyncUdpSocket *,const char *, size_t, const rtc::SocketAddress &,const int64_t &>
            SignalReadPacket;
#if 0
        State GetState() const override;
        int GetOption(rtc::Socket::Option opt, int *value) override;
        int SetOption(rtc::Socket::Option opt, int value) override;
        int GetError() const override;
        void SetError(int error) override;
             rtc::SocketAddress GetLocalAddress() const override;
        rtc::SocketAddress GetRemoteAddress() const override;
#endif

    private:
        int AddUdpPacket(const char *data, size_t size, const rtc::SocketAddress &addr);

    private:
        EventLoop *el_;
        IOWatcher *socket_watcher_;
        // std::unique_ptr<PhysicalSocketEx> psock_;
        int socket_ = 0;
        char *buf_;
        size_t size_;

        std::list<UdpPacketData *> udp_packet_list_;
    };

} // namespace ice

#endif // ICE_BASE_LINUX_ASYNC_UDP_SOCKET_H_
